#include "Ringbuffer.h"
#include "string.h"
#include "def.h"
/*
* 环形队列初始化
*/
int32_t RingBuffer_Init(ADPT_RingBufferStru *ptrRb, uint8_t *ptrBuf, uint32_t size)
{
    RETURN_ERROR_IF (ptrRb == NULL || ptrBuf == NULL || size == 0);
    ptrRb->capcity = size;
    ptrRb->read_index = 0;
    ptrRb->write_index = 0;
    ptrRb->ptrBuffer = ptrBuf;
    memset(ptrRb->ptrBuffer, 0, size);
    return 0;
}

/*
*环形队列写单个字节
*/
int32_t RingBuffer_Write_One_Byte(ADPT_RingBufferStru *ptrRb, uint8_t dataIn)
{
    RETURN_ERROR_IF (ptrRb == NULL);
    if (ptrRb->write_index >= ptrRb->capcity) {
        ptrRb->write_index = 0;
    }
    ptrRb->ptrBuffer[ptrRb->write_index] = dataIn;
    ptrRb->write_index++;
    if (ptrRb->write_index == ptrRb->read_index) { // 写索引追上了读索引
        ptrRb->read_index++; // 读索引自加，读索引原来指向的数据已经被覆盖
        if (ptrRb->read_index >= ptrRb->capcity) {
            ptrRb->read_index = 0;
        }
    }
    return 0;
}

/*
*环形队列写多个字节,写入长度超过了对列剩余容量则截断写入
*/
int32_t RingBuffer_Write_Some_Byte(ADPT_RingBufferStru *ptrRb, uint8_t *ptrDataIn, uint32_t len)
{
    RETURN_ERROR_IF (ptrRb == NULL || ptrDataIn == NULL);
    if (ptrRb->write_index >= ptrRb->capcity) {
        ptrRb->write_index = 0;
    }
    uint32_t writeLen = len > Get_RingBuffer_RemainSizes(ptrRb) ? Get_RingBuffer_RemainSizes(ptrRb) : len;
    memcpy(ptrRb->ptrBuffer, ptrDataIn, writeLen);
    ptrRb->write_index += writeLen;
    if (ptrRb->write_index == ptrRb->read_index) { // 写索引追上了读索引
        ptrRb->read_index++; // 读索引自加，读索引原来指向的数据已经被覆盖
        if (ptrRb->read_index >= ptrRb->capcity) {
            ptrRb->read_index = 0;
        }
    }
    return 0;
}

/*
*  环形队列读取单个字节
*/
int32_t RingBuffer_ReadOneByte(ADPT_RingBufferStru *ptrRb, uint8_t *dataOut)
{
    RETURN_ERROR_IF (Is_RingBuffer_Empty(ptrRb));
    *dataOut = ptrRb->ptrBuffer[ptrRb->read_index];
    ptrRb->read_index++;
    if (ptrRb->read_index >= ptrRb->capcity) {
        ptrRb->read_index = 0;
    }
    return 0;
}

/*
*  环形队列读取多个字节
*/
int32_t RingBuffer_ReadSomeByte(ADPT_RingBufferStru *ptrRb, uint8_t *ptrDataOut, uint32_t len)
{
    RETURN_ERROR_IF (ptrRb == NULL || ptrDataOut == NULL || Is_RingBuffer_Empty(ptrRb) || len > ptrRb->capcity || Get_RingBuffer_RemainSizes(ptrRb) < len);
    memcpy(ptrDataOut, ptrRb->ptrBuffer, len);
    ptrRb->read_index += len;
    if (ptrRb->read_index >= ptrRb->capcity) {
        ptrRb->read_index = 0;
    }
    return 0;
}

int Is_RingBuffer_Full(ADPT_RingBufferStru *ptrRb)
{
    RETURN_ERROR_IF (ptrRb == NULL);
    return ((ptrRb->write_index + 1) % ptrRb->capcity == ptrRb->read_index);
}

int Is_RingBuffer_Empty(ADPT_RingBufferStru *ptrRb)
{
    RETURN_ERROR_IF (ptrRb == NULL);
    return (ptrRb->read_index == ptrRb->write_index);
}

int Get_RingBuffer_RemainSizes(ADPT_RingBufferStru *ptrRb)
{
    RETURN_ERROR_IF (ptrRb == NULL);
    return (ptrRb->capcity - ptrRb->write_index + ptrRb->read_index);
}

// 接收环形队列，读取的时候要关闭中断或者添加互斥控制量
// 普通收发中断的做法
// 数据接收的时候，一个字节一个字节地接收，扔进接收队列里面，数据要读取的时候，先获取互斥控制变量A，再
// 从接收队列读取，最后释放互斥控制变量A
// 发送环形队列，先获取互斥控制变量A，然后将要发送的数据扔进发送队列，同时打开发送中断，再释放互斥控制变量A
// 发送中断响应之后，从发送队列里面读取数据一个个字节发送出去，直到发送完之后才清除发送中断标志
// DMA+空闲中断
// 中断收到一堆数据，扔进队列并且通知其他线程，该队列数据可用，其他线程想要用该数据，先获取队列，如果
// 该队列为空则阻塞等待，等等时间节拍可设定
// 发送数据到队列，另一个线程定时获取队列里面是否有数据，有的话则调用底层串口发送dma传输接口发送数据
// cpu + cache + ram + dma + perphe
//example irq handler

//void uart_irq(void) {
//    if(receive_Data_flag){
//        RingBuffer_Push..
//        rx_flag = 0;
//    } else if (tx_flag) {
//        RingBuffer_Pop..
//        tx_flag = 0;
//        // send_data..
//        // transmit_data..
//    }
//}

#if 0
#define RX_Length_Limit 64
uint8_t g_adptRingBuf[256] = { 0 };
ADPT_RingBufferStru g_adptRing;
//example while loop
int main(int argc, char **argv) { 
    bsp_init();
    RingBuffer_Init(&g_adptRing, (uint8_t*)g_adptRingBuf, sizeof(g_adptRingBuf));
    while(1) {
        if(Is_RingBuffer_Full(&g_adptRingBuf) && Get_RingBufferLength(&g_adptRingBuf) >= RX_Length_Limit){
            // buffer is full, do something here
            uint8_t data = 0;
            RingBuffer_Read(&g_adptRingBuf, &data, sizeof(data));
            uint8_t Buffer[64];
            RingBuffer_ReadSomeByte(&g_adptRingBuf, &Buffer, sizeof(Buffer));
            continue;
        }
    }
}
#endif

